package rest

import (
	"fmt"
	"strconv"

	"github.com/pkg/errors"

	"bmember/pkg/lueerror"

	"github.com/labstack/echo/v4"

	pb "bmember/api/pb/server"
	"bmember/internal/service"
)

type mHandler struct {
	*Base
	Name string
}

// NewMemberHandler 会员相关handler
func NewMemberHandler() *mHandler {
	return &mHandler{
		Base: base,
		Name: "member_related_handler",
	}
}

// Register 路由
func (hl *mHandler) Register(r *echo.Group) {
	hl.adminRegister(r)
	r.POST("/v1/say-hello", hl.sayHello)
	// 会员检查
	r.POST("/v1/check", hl.checkMember)
	// 会员注册
	r.POST("/v1/platform/register", hl.platformMemberRegister)
	// 会员信息更新
	r.PUT("/v1/info/update", hl.updateMember)
	// 成为会员
	r.POST("/v1/join", hl.joinMember)
	// 获取账号信息
	r.GET("/v1/account/info", hl.getAccountInfo)
	// 第三方品牌登录
	r.POST("/v1/platform/login", hl.platformLogin)
	// 创建地址
	r.POST("/v1/address/create", hl.createAddress)
	// 更新地址
	r.PUT("/v1/address/update", hl.updateAddress)
	// 获取地址列表
	r.GET("/v1/address/list", hl.getAddresses)
	// 地址搜索
	r.GET("/v1/address/search", hl.addressSearch)
	// 地址解析
	r.GET("/v1/address/parse", hl.getAddressLocation)
	// 根据坐标搜索地址
	r.GET("/v1/geo/address", hl.getAddressByLocation)
	// 删除地址
	r.DELETE("/v1/addresses/:addr_id", hl.deleteAddress)
	// 微信加密手机号绑定用户
	r.PUT("/v1/wechat/encrypted-mobile/bind", hl.wechatMobileBind)
	// 会员更新手机号
	r.PUT("/v1/mobile/bind", hl.updateMobile)
	// 发送短信验证码
	r.POST("/v1/mobile/verify-code/send", hl.sendMobileCode)
}

func (hl *mHandler) sayHello(c echo.Context) error {
	req := &pb.HelloReq{}
	if errL := hl.ParseBody(c, req); errL != nil {
		return errL
	}
	resp := fmt.Sprintf("hello %s your, id is %d", req.Name, req.Id)

	reply := &pb.HelloReply{
		Message: resp,
	}

	return hl.SimpleRet(c, reply, nil)
}

// check member
func (hl *mHandler) checkMember(c echo.Context) error {
	ctx := c.Request().Context()
	req := &pb.MemberCheckReq{}
	if errL := hl.ParseBody(c, req); errL != nil {
		return errL
	}
	ret, errL := service.GetMemberSrv().MemberLogin(ctx, req)
	if errL != nil {
		return errL
	}
	if ret.IsRegister {
		ret.Token, errL = service.GetService().GenJwtToken(ret.MemberId, ret.BrandId, ret.OpenId, ret.AppId, req.Channel)
	}
	return hl.SimpleRet(c, ret, errL)
}

// 从平台侧注册会员
func (hl *mHandler) platformMemberRegister(c echo.Context) error {
	ctx := c.Request().Context()
	req := &pb.MemberRegisterReq{}
	if errL := hl.ParseBody(c, req); errL != nil {
		return errL
	}
	ret, errL := service.GetMemberSrv().PlatMemberRegister(ctx, req)
	if errL != nil {
		return errL
	}
	if ret.IsRegister {
		ret.Token, errL = service.GetService().GenJwtToken(ret.MemberId, ret.BrandId, ret.OpenId, ret.AppId, req.Channel)
	}
	return hl.SimpleRet(c, ret, errL)
}

func (hl *mHandler) platformLogin(c echo.Context) error {
	ctx := c.Request().Context()
	req := &pb.MemberPlatformLoginReq{}
	if errL := hl.ParseBody(c, req); errL != nil {
		return errL
	}
	ret, errL := service.GetMemberSrv().PlatformLogin(ctx, req)
	if errL != nil {
		return errL
	}
	if ret.IsRegister {
		ret.Token, errL = service.GetService().GenJwtToken(ret.MemberId, ret.BrandId, ret.OpenId, ret.AppId, req.Channel)
	}
	return hl.SimpleRet(c, ret, errL)
}

func (hl *mHandler) updateMember(c echo.Context) error {
	ctx := c.Request().Context()
	token, errL := hl.VerifyJwtToken(c)
	if errL != nil {
		return errL
	}
	req := &pb.MemberUpdateReq{}
	if errL = hl.ParseBody(c, req); errL != nil {
		return errL
	}
	ret, errL := service.GetMemberSrv().MemberUpdate(ctx, token.BrandID, token.MemberID, req)
	if errL != nil {
		return errL
	}
	ret.AppId = token.AppID
	ret.OpenId = token.OpenID
	return hl.SimpleRet(c, ret, errL)
}

func (hl *mHandler) joinMember(c echo.Context) error {
	ctx := c.Request().Context()
	token, errL := hl.VerifyJwtToken(c)
	if errL != nil {
		return errL
	}
	req := &pb.MemberUpdateReq{}
	if errL = hl.ParseBody(c, req); errL != nil {
		return errL
	}
	req.MemberId = token.MemberID
	ret, errL := service.GetMemberSrv().JoinMember(ctx, token.BrandID, token.MemberID, req)
	return hl.SimpleRet(c, ret, errL)
}

// 获取账号信息
func (hl *mHandler) getAccountInfo(c echo.Context) error {
	ctx := c.Request().Context()
	token, errL := hl.VerifyJwtToken(c)
	if errL != nil {
		return errL
	}
	ret, errL := service.GetMemberSrv().GetMemberAccount(ctx, token.BrandID, token.MemberID)
	return hl.SimpleRet(c, ret, errL)
}

// 创建收货地址
func (hl *mHandler) createAddress(c echo.Context) error {
	ctx := c.Request().Context()
	token, errL := hl.VerifyJwtToken(c)
	if errL != nil {
		return errL
	}
	req := &pb.MemberAddressCreateReq{}
	if errL = hl.ParseBody(c, req); errL != nil {
		return errL
	}
	if errL = hl.MobileCheck(req.ContactMobile); errL != nil {
		return errL
	}
	ret, errL := service.GetMemberSrv().CreateMemberAddress(ctx, token.BrandID, token.MemberID, req)
	return hl.SimpleRet(c, ret, errL)
}

func (hl *mHandler) updateAddress(c echo.Context) error {
	ctx := c.Request().Context()
	token, errL := hl.VerifyJwtToken(c)
	if errL != nil {
		return errL
	}
	req := &pb.MemberAddressUpdateReq{}
	if errL = hl.ParseBody(c, req); errL != nil {
		return errL
	}
	if req.ContactMobile != "" {
		if errL = hl.MobileCheck(req.ContactMobile); errL != nil {
			return errL
		}
	}
	ret, errL := service.GetMemberSrv().UpdateMemberAddress(ctx, token.MemberID, req)
	return hl.SimpleRet(c, ret, errL)
}

func (hl *mHandler) getAddresses(c echo.Context) error {
	ctx := c.Request().Context()
	token, errL := hl.VerifyJwtToken(c)
	if errL != nil {
		return errL
	}
	ret, errL := service.GetMemberSrv().GetAddressList(ctx, token.MemberID)
	return hl.SimpleRet(c, ret, errL)
}

func (hl *mHandler) addressSearch(c echo.Context) error {
	ctx := c.Request().Context()
	_, errL := hl.VerifyJwtToken(c)
	if errL != nil {
		return errL
	}
	address := c.QueryParam("address")
	region := c.QueryParam("region")
	lats := c.QueryParam("latitude")
	lngs := c.QueryParam("longitude")
	if address == "" {
		return lueerror.InvalidRequest(errors.New("address, latitude, longitude 参数都必填"))
	}
	var lat, lng float64
	var err error
	if lats != "" {
		lat, err = strconv.ParseFloat(lats, 64)
		if err != nil {
			return lueerror.InvalidRequest(err)
		}
	}
	if lngs != "" {
		lng, err = strconv.ParseFloat(lngs, 64)
		if err != nil {
			return lueerror.InvalidRequest(err)
		}
	}
	ret, errL := service.GetMemberSrv().AddressSearch(ctx, address, region, lat, lng)
	return hl.SimpleRet(c, ret, errL)
}

func (hl *mHandler) getAddressByLocation(c echo.Context) error {
	ctx := c.Request().Context()
	_, errL := hl.VerifyJwtToken(c)
	if errL != nil {
		return errL
	}
	lats := c.QueryParam("latitude")
	lngs := c.QueryParam("longitude")
	if lats == "" || lngs == "" {
		return lueerror.InvalidRequest(errors.New("address, latitude, longitude 参数都必填"))
	}
	lat, err := strconv.ParseFloat(lats, 64)
	if err != nil {
		return lueerror.InvalidRequest(err)
	}
	lng, err := strconv.ParseFloat(lngs, 64)
	if err != nil {
		return lueerror.InvalidRequest(err)
	}
	ret, errL := service.GetMemberSrv().GetAddressByLocation(ctx, lat, lng)
	return hl.SimpleRet(c, ret, errL)
}

func (hl *mHandler) getAddressLocation(c echo.Context) error {
	ctx := c.Request().Context()
	_, errL := hl.VerifyJwtToken(c)
	if errL != nil {
		return errL
	}
	address := c.QueryParam("address")
	region := c.QueryParam("city")
	if address == "" {
		return lueerror.InvalidRequest(errors.New("地址必填"))
	}
	ret, errL := service.GetMemberSrv().GetAddressLocation(ctx, address, region)
	return hl.SimpleRet(c, ret, errL)
}

func (hl *mHandler) deleteAddress(c echo.Context) error {
	ctx := c.Request().Context()
	token, errL := hl.VerifyJwtToken(c)
	if errL != nil {
		return errL
	}
	addr := c.Param("addr_id")
	addrId, err := strconv.ParseInt(addr, 10, 64)
	if err != nil {
		return lueerror.InvalidRequest(err)
	}
	errL = service.GetMemberSrv().DeleteAddress(ctx, token.MemberID, addrId)
	return hl.SimpleRet(c, nil, errL)
}

func (hl *mHandler) updateMobile(c echo.Context) error {
	ctx := c.Request().Context()
	token, errL := hl.VerifyJwtToken(c)
	if errL != nil {
		return errL
	}
	req := &pb.UpdateMemberMobileReq{}
	if errL = hl.ParseBody(c, req); errL != nil {
		return errL
	}
	ret, errL := service.GetMemberSrv().MemberMobileBinding(ctx, token.BrandID, token.MemberID, req.Mobile, req.CodeType, req.Code)
	if errL != nil {
		return errL
	}
	newToken, errL := service.GetService().GenJwtToken(ret.MemberId, token.BrandID, token.OpenID, token.AppID, token.BilinApp)
	if errL != nil {
		return errL
	}
	ret.OpenId = token.OpenID
	ret.AppId = token.AppID
	ret.Token = newToken
	return hl.SimpleRet(c, ret, nil)
}

func (hl *mHandler) wechatMobileBind(c echo.Context) error {
	ctx := c.Request().Context()
	token, errL := hl.VerifyJwtToken(c)
	if errL != nil {
		return errL
	}
	req := &pb.WechatEncryptedMobileBindReq{}
	if errL = hl.ParseBody(c, req); errL != nil {
		return errL
	}
	ret, errL := service.GetMemberSrv().EncryptedMobileBinding(ctx, token.BrandID, token.MemberID, token.AppID,
		token.OpenID, req.EncryptedData, req.Iv, token.BilinApp)
	if errL != nil {
		return errL
	}
	newToken, errL := service.GetService().GenJwtToken(ret.MemberId, token.BrandID, token.OpenID, token.AppID, token.BilinApp)
	if errL != nil {
		return errL
	}
	ret.OpenId = token.OpenID
	ret.AppId = token.AppID
	ret.Token = newToken
	return hl.SimpleRet(c, ret, nil)
}

func (hl *mHandler) sendMobileCode(c echo.Context) error {
	ctx := c.Request().Context()
	_, errL := hl.VerifyJwtToken(c)
	if errL != nil {
		return errL
	}
	req := &pb.SendMobileVerifyCodeReq{}
	if errL = hl.ParseBody(c, req); errL != nil {
		return errL
	}
	if errL = hl.MobileCheck(req.Mobile); errL != nil {
		return errL
	}
	errL = service.GetService().SendMobileVerifyCode(ctx, req.Mobile, req.CodeType)
	if errL != nil {
		return errL
	}
	return hl.SimpleRet(c, &pb.SendMobileVerifyCodeReply{Message: "OK"}, nil)
}
